package hn.sigit.model.hnd.cadastre;

import hn.sigit.logic.geometry.GeometryOperations;
import hn.sigit.logic.ladm.ResponsibilitiesUtil;
import hn.sigit.logic.ladm.RestrictionsUtil;
import hn.sigit.logic.ladm.RightsUtil;
import hn.sigit.model.ladm.administrative.LA_AdministrativeSource;
import hn.sigit.model.ladm.administrative.LA_BAUnit;
import hn.sigit.model.ladm.administrative.LA_RRR;
import hn.sigit.model.ladm.administrative.LA_RequiredRelationshipBAUnit;
import hn.sigit.model.ladm.spatialunit.LA_SpatialUnit;
import hn.sigit.model.ladm.spatialunit.surveyingandrepresentation.LA_SpatialSource;
import hn.sigit.util.PropertyResponsibilitiesComparable;
import hn.sigit.util.PropertyRestrictionsComparable;
import hn.sigit.util.PropertyRightsComparable;
import hn.sigit.util.ResponsibilitiesComparable;
import hn.sigit.util.RestrictionsComparable;
import hn.sigit.util.RightsComparable;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.*;

import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon;

@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="HND_Property", schema="hnd_cadastre")
@Inheritance(strategy=InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name="LA_BAUnitID", referencedColumnName="ID")
public class HND_Property extends LA_BAUnit implements Serializable, Cloneable, PropertyRightsComparable, PropertyRestrictionsComparable, PropertyResponsibilitiesComparable {
	private static final long serialVersionUID = 1L;
	

	public HND_Property() {
	}
	
	
	@Transient
	public Set<HND_Parcel> getParcels() {
		Set<LA_SpatialUnit> suSet = super.getSpatialUnits();
		Set<HND_Parcel> parcelSet = new HashSet<HND_Parcel>();

		for (LA_SpatialUnit lasu : suSet)
			if (lasu instanceof HND_Parcel)
				parcelSet.add((HND_Parcel) lasu);

		return parcelSet;
	}

	
	@Transient
	public MultiPolygon getParcelsAsMultiPolygon() {
		Set<HND_Parcel> parcels = getParcels();
		
		if (parcels != null && parcels.size() > 0) {
			Polygon[] polygons = new Polygon[parcels.size()];
			int i = 0;
			for (HND_Parcel hndP : parcels)
				polygons[i++] = hndP.getShape();
			
			
			return GeometryOperations.geomFactory.createMultiPolygon(polygons);
		}
		
		return null;
	}

	@Transient
	public String toString() {
		return super.toString();
	}

	
	@Override
	public HND_Property clone() {
		HND_Property clonedHndPropery;
		try {
			clonedHndPropery = (HND_Property) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}

		//this is in order to mark the object as unsaved
		clonedHndPropery.setuID(0);
		
		Set<LA_SpatialSource> spatialSources = new HashSet<LA_SpatialSource>(getSpatialSources());
		Set<LA_RRR> rrr = new HashSet<LA_RRR>(getRrr());
		Set<LA_RequiredRelationshipBAUnit> baunits1requiredrelationshipbaunits = new HashSet<LA_RequiredRelationshipBAUnit>(getBaunits1La_requiredrelationshipbaunits());
		Set<LA_RequiredRelationshipBAUnit> baunits2requiredrelationshipbaunits = new HashSet<LA_RequiredRelationshipBAUnit>(getBaunits2La_requiredrelationshipbaunits());
		Set<LA_SpatialUnit> spatialUnits = new HashSet<LA_SpatialUnit>(getSpatialUnits());
		Set<LA_AdministrativeSource> adminSources = new HashSet<LA_AdministrativeSource>(getAdminSources());
		
		clonedHndPropery.setSpatialSources(spatialSources);
		clonedHndPropery.setRrr(rrr);
		clonedHndPropery.setBaunits1La_requiredrelationshipbaunits(baunits1requiredrelationshipbaunits);
		clonedHndPropery.setBaunits2La_requiredrelationshipbaunits(baunits2requiredrelationshipbaunits);
		clonedHndPropery.setSpatialUnits(spatialUnits);
		clonedHndPropery.setAdminSources(adminSources);

		return clonedHndPropery;
	}

	@Transient
	@Override
	public boolean equalPropertyRights(PropertyRightsComparable other) {
		return RightsUtil.propertyRightsEqual(this, other);
	}

	@Transient
	@Override
	public int propertyRightsHash() {
		int hash = 0;
		for (RightsComparable rc : getRightsComparableList())
			hash +=	rc.rightsHash();
		return hash;
	}

	@Transient
	@Override
	public List<RightsComparable> getRightsComparableList() {
		List<RightsComparable> rightsComparableList = new ArrayList<RightsComparable>();
		for (LA_RRR laRrr : getRrr())
			if (laRrr instanceof RightsComparable)
				rightsComparableList.add((RightsComparable) laRrr);
		return rightsComparableList;
	}


	@Transient
	@Override
	public boolean equalPropertyResponsibilities(PropertyResponsibilitiesComparable other) {
		return ResponsibilitiesUtil.propertyResponsibilitiesEqual(this, other);
	}

	@Transient
	@Override
	public int propertyResponsibilitiesHash() {
		int hash = 0;
		for (ResponsibilitiesComparable rc : getResponsibilitiesComparableList())
			hash += rc.responsibilitiesHash();
		return hash;
	}

	@Transient
	@Override
	public List<ResponsibilitiesComparable> getResponsibilitiesComparableList() {
		List<ResponsibilitiesComparable> responsibilitiesComparableList = new ArrayList<ResponsibilitiesComparable>();
		for (LA_RRR laRrr : getRrr())
			if (laRrr instanceof ResponsibilitiesComparable)
				responsibilitiesComparableList.add((ResponsibilitiesComparable) laRrr);
		return responsibilitiesComparableList;
	}


	@Transient
	@Override
	public boolean equalRestrictions(PropertyRestrictionsComparable other) {
		return RestrictionsUtil.propertyRestrictionsEqual(this, other);
	}

	@Transient
	@Override
	public int propertyRestrictionsHash() {
		int hash = 0;
		for (RestrictionsComparable rc : getRestrictionsComparableList())
			hash += rc.restrictionsHash();
		return hash;
	}

	@Transient
	@Override
	public List<RestrictionsComparable> getRestrictionsComparableList() {
		List<RestrictionsComparable> restrictionsComparableList = new ArrayList<RestrictionsComparable>();
		for (LA_RRR laRrr : getRrr())
			if (laRrr instanceof RestrictionsComparable)
				restrictionsComparableList.add((RestrictionsComparable) laRrr);
		return restrictionsComparableList;
	}
}
